image, picture: Move pixbuf code to gdkpixbufutils
authorMatthias Clasen <mclasen@redhat.com>
Fri, 16 Apr 2021 21:17:26 +0000 (17:17 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Fri, 16 Apr 2021 22:27:40 +0000 (18:27 -0400)
This cleans up and moves the code to load files
while taking the scale into account. Along the way,
we drop the last uses of GdkPixbufAnimation, and
consolidate the pixbuf using code in one place.

gtk/gdkpixbufutils.c
gtk/gdkpixbufutilsprivate.h
gtk/gtkimage.c
gtk/gtkpicture.c

index 2aa62b094c505a47e128a0bf01c7dfd2493369cc..d1b6693918161d137f95f6681dfc86f7955bb7af 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <gdk/gdk.h>
 #include "gdkpixbufutilsprivate.h"
+#include "gtkscalerprivate.h"
 
 static GdkPixbuf *
 load_from_stream (GdkPixbufLoader  *loader,
@@ -572,3 +573,130 @@ gtk_make_symbolic_texture_from_file (GFile       *file,
 
   return texture;
 }
+
+typedef struct {
+  int scale_factor;
+} LoaderData;
+
+static void
+on_loader_size_prepared (GdkPixbufLoader *loader,
+                         int              width,
+                         int              height,
+                         gpointer         user_data)
+{
+  LoaderData *loader_data = user_data;
+  GdkPixbufFormat *format;
+
+  /* Let the regular icon helper code path handle non-scalable images */
+  format = gdk_pixbuf_loader_get_format (loader);
+  if (!gdk_pixbuf_format_is_scalable (format))
+    {
+      loader_data->scale_factor = 1;
+      return;
+    }
+
+  gdk_pixbuf_loader_set_size (loader,
+                              width * loader_data->scale_factor,
+                              height * loader_data->scale_factor);
+}
+
+GdkPaintable *
+gdk_paintable_new_from_bytes_scaled (GBytes *bytes,
+                                     int     scale_factor)
+{
+  GdkPixbufLoader *loader;
+  GdkPixbuf *pixbuf = NULL;
+  LoaderData loader_data;
+  GdkTexture *texture;
+  GdkPaintable *paintable;
+
+  loader_data.scale_factor = scale_factor;
+
+  loader = gdk_pixbuf_loader_new ();
+  g_signal_connect (loader, "size-prepared",
+                    G_CALLBACK (on_loader_size_prepared), &loader_data);
+
+  if (!gdk_pixbuf_loader_write_bytes (loader, bytes, NULL))
+    goto out;
+
+  if (!gdk_pixbuf_loader_close (loader, NULL))
+    goto out;
+
+  pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+  if (pixbuf != NULL)
+    g_object_ref (pixbuf);
+
+ out:
+  gdk_pixbuf_loader_close (loader, NULL);
+  g_object_unref (loader);
+
+  if (!pixbuf)
+    return NULL;
+
+  texture = gdk_texture_new_for_pixbuf (pixbuf);
+  if (loader_data.scale_factor != 1)
+    paintable = gtk_scaler_new (GDK_PAINTABLE (texture), loader_data.scale_factor);
+  else
+    paintable = g_object_ref ((GdkPaintable *)texture);
+
+  g_object_unref (pixbuf);
+  g_object_unref (texture);
+
+  return paintable;
+}
+
+GdkPaintable *
+gdk_paintable_new_from_path_scaled (const char *path,
+                                    int         scale_factor)
+{
+  char *contents;
+  gsize length;
+  GBytes *bytes;
+  GdkPaintable *paintable;
+
+  if (!g_file_get_contents (path, &contents, &length, NULL))
+    return NULL;
+
+  bytes = g_bytes_new_take (contents, length);
+
+  paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor);
+
+  g_bytes_unref (bytes);
+
+  return paintable;
+}
+
+GdkPaintable *
+gdk_paintable_new_from_resource_scaled (const char *path,
+                                        int         scale_factor)
+{
+  GBytes *bytes;
+  GdkPaintable *paintable;
+
+  bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+  if (!bytes)
+    return NULL;
+
+  paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor);
+  g_bytes_unref (bytes);
+
+  return paintable;
+}
+
+GdkPaintable *
+gdk_paintable_new_from_file_scaled (GFile *file,
+                                    int    scale_factor)
+{
+  GBytes *bytes;
+  GdkPaintable *paintable;
+
+  bytes = g_file_load_bytes (file, NULL, NULL, NULL);
+  if (!bytes)
+    return NULL;
+
+  paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor);
+
+  g_bytes_unref (bytes);
+
+  return paintable;
+}
index 2a339d2c420e5d90f0ad4d1a04c77a6c7c311aec..62efe3699ebeb545e003b051dbd5b6aa129dde33 100644 (file)
@@ -86,6 +86,16 @@ GdkTexture *gtk_make_symbolic_texture_from_resource (const char    *path,
                                                      int            height,
                                                      double         scale,
                                                      GError       **error);
+
+GdkPaintable *gdk_paintable_new_from_bytes_scaled    (GBytes        *bytes,
+                                                      int            scale_factor);
+GdkPaintable *gdk_paintable_new_from_path_scaled     (const char    *path,
+                                                      int            scale_factor);
+GdkPaintable *gdk_paintable_new_from_resource_scaled (const char    *path,
+                                                      int            scale_factor);
+GdkPaintable *gdk_paintable_new_from_file_scaled     (GFile         *file,
+                                                      int            scale_factor);
+
 G_END_DECLS
 
 #endif  /* __GDK_PIXBUF_UTILS_PRIVATE_H__ */
index abe5694c71aa8fdff48e64e91086e79c1c377ab3..46a494c73832887df5c7fe6d25b19ad298bfeea0 100644 (file)
 #include "gtkicontheme.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
-#include "gtkscalerprivate.h"
 #include "gtksnapshot.h"
 #include "gtktypebuiltins.h"
 #include "gtkwidgetprivate.h"
+#include "gdkpixbufutilsprivate.h"
 
 #include <math.h>
 #include <string.h>
@@ -581,96 +581,6 @@ gtk_image_new_from_gicon (GIcon *icon)
   return GTK_WIDGET (image);
 }
 
-typedef struct {
-  GtkImage *image;
-  int scale_factor;
-} LoaderData;
-
-static void
-on_loader_size_prepared (GdkPixbufLoader *loader,
-                        int              width,
-                        int              height,
-                        gpointer         user_data)
-{
-  LoaderData *loader_data = user_data;
-  int scale_factor;
-  GdkPixbufFormat *format;
-
-  /* Let the regular icon helper code path handle non-scalable images */
-  format = gdk_pixbuf_loader_get_format (loader);
-  if (!gdk_pixbuf_format_is_scalable (format))
-    {
-      loader_data->scale_factor = 1;
-      return;
-    }
-
-  scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (loader_data->image));
-  gdk_pixbuf_loader_set_size (loader, width * scale_factor, height * scale_factor);
-  loader_data->scale_factor = scale_factor;
-}
-
-static GdkPixbufAnimation *
-load_scalable_with_loader (GtkImage    *image,
-                          const char *file_path,
-                          const char *resource_path,
-                          int         *scale_factor_out)
-{
-  GdkPixbufLoader *loader;
-  GBytes *bytes;
-  char *contents;
-  gsize length;
-  gboolean res;
-  GdkPixbufAnimation *animation;
-  LoaderData loader_data;
-
-  animation = NULL;
-  bytes = NULL;
-
-  loader = gdk_pixbuf_loader_new ();
-  loader_data.image = image;
-
-  g_signal_connect (loader, "size-prepared", G_CALLBACK (on_loader_size_prepared), &loader_data);
-
-  if (resource_path != NULL)
-    {
-      bytes = g_resources_lookup_data (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
-    }
-  else if (file_path != NULL)
-    {
-      res = g_file_get_contents (file_path, &contents, &length, NULL);
-      if (res)
-       bytes = g_bytes_new_take (contents, length);
-    }
-  else
-    {
-      g_assert_not_reached ();
-    }
-
-  if (!bytes)
-    goto out;
-
-  if (!gdk_pixbuf_loader_write_bytes (loader, bytes, NULL))
-    goto out;
-
-  if (!gdk_pixbuf_loader_close (loader, NULL))
-    goto out;
-
-  animation = gdk_pixbuf_loader_get_animation (loader);
-  if (animation != NULL)
-    {
-      g_object_ref (animation);
-      if (scale_factor_out != NULL)
-       *scale_factor_out = loader_data.scale_factor;
-    }
-
- out:
-  gdk_pixbuf_loader_close (loader, NULL);
-  g_object_unref (loader);
-  g_bytes_unref (bytes);
-
-  return animation;
-}
-
 /**
  * gtk_image_set_from_file: (attributes org.gtk.Method.set_property=file)
  * @image: a `GtkImage`
@@ -681,18 +591,16 @@ load_scalable_with_loader (GtkImage    *image,
  * See [ctor@Gtk.Image.new_from_file] for details.
  */
 void
-gtk_image_set_from_file   (GtkImage    *image,
-                           const char *filename)
+gtk_image_set_from_file (GtkImage    *image,
+                         const char *filename)
 {
-  GdkPixbufAnimation *anim;
   int scale_factor;
-  GdkTexture *texture;
-  GdkPaintable *scaler;
+  GdkPaintable *paintable;
 
   g_return_if_fail (GTK_IS_IMAGE (image));
 
   g_object_freeze_notify (G_OBJECT (image));
-  
+
   gtk_image_clear (image);
 
   if (filename == NULL)
@@ -702,23 +610,19 @@ gtk_image_set_from_file   (GtkImage    *image,
       return;
     }
 
-  anim = load_scalable_with_loader (image, filename, NULL, &scale_factor);
+  scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (image));
+  paintable = gdk_paintable_new_from_path_scaled (filename, scale_factor);
 
-  if (anim == NULL)
+  if (paintable == NULL)
     {
       gtk_image_set_from_icon_name (image, "image-missing");
       g_object_thaw_notify (G_OBJECT (image));
       return;
     }
 
-  texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_animation_get_static_image (anim));
-  scaler = gtk_scaler_new (GDK_PAINTABLE (texture), scale_factor);
-
-  gtk_image_set_from_paintable (image, scaler);
+  gtk_image_set_from_paintable (image, paintable);
 
-  g_object_unref (scaler);
-  g_object_unref (texture);
-  g_object_unref (anim);
+  g_object_unref (paintable);
 
   image->filename = g_strdup (filename);
 
@@ -765,13 +669,11 @@ out:
  * See [ctor@Gtk.Image.new_from_resource] for details.
  */
 void
-gtk_image_set_from_resource (GtkImage    *image,
-                            const char *resource_path)
+gtk_image_set_from_resource (GtkImage   *image,
+                             const char *resource_path)
 {
-  GdkPixbufAnimation *animation;
-  int scale_factor = 1;
-  GdkTexture *texture;
-  GdkPaintable *scaler;
+  int scale_factor;
+  GdkPaintable *paintable;
 
   g_return_if_fail (GTK_IS_IMAGE (image));
 
@@ -788,34 +690,29 @@ gtk_image_set_from_resource (GtkImage    *image,
   if (resource_is_pixdata (resource_path))
     {
       g_warning ("GdkPixdata format images are not supported, remove the \"to-pixdata\" option from your GResource files");
-      animation = NULL;
+      paintable = NULL;
     }
   else
     {
-      animation = load_scalable_with_loader (image, NULL, resource_path, &scale_factor);
+      scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (image));
+      paintable = gdk_paintable_new_from_resource_scaled (resource_path, scale_factor);
     }
 
-  if (animation == NULL)
+  if (paintable == NULL)
     {
       gtk_image_set_from_icon_name (image, "image-missing");
       g_object_thaw_notify (G_OBJECT (image));
       return;
     }
 
-  texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_animation_get_static_image (animation));
-  scaler = gtk_scaler_new (GDK_PAINTABLE (texture), scale_factor);
-
-  gtk_image_set_from_paintable (image, scaler);
+  gtk_image_set_from_paintable (image, paintable);
 
-  g_object_unref (scaler);
-  g_object_unref (texture);
+  g_object_unref (paintable);
 
   image->resource_path = g_strdup (resource_path);
 
   g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_RESOURCE]);
 
-  g_object_unref (animation);
-
   g_object_thaw_notify (G_OBJECT (image));
 }
 
index 10607b31aee9fa088b2c4ed991d7b345067d0d15..6b9fb1c51efece69cc7257a2108ec114d79eaf6e 100644 (file)
@@ -26,9 +26,9 @@
 #include "gtkcssstyleprivate.h"
 #include "gtkintl.h"
 #include "gtkprivate.h"
-#include "gtkscalerprivate.h"
 #include "gtksnapshot.h"
 #include "gtkwidgetprivate.h"
+#include "gdkpixbufutilsprivate.h"
 
 /**
  * GtkPicture:
@@ -560,77 +560,6 @@ gtk_picture_new_for_resource (const char *resource_path)
   return result;
 }
 
-typedef struct {
-  int scale_factor;
-} LoaderData;
-
-static void
-on_loader_size_prepared (GdkPixbufLoader *loader,
-                        int              width,
-                        int              height,
-                        gpointer         user_data)
-{
-  LoaderData *loader_data = user_data;
-  GdkPixbufFormat *format;
-
-  /* Let the regular icon helper code path handle non-scalable pictures */
-  format = gdk_pixbuf_loader_get_format (loader);
-  if (!gdk_pixbuf_format_is_scalable (format))
-    {
-      loader_data->scale_factor = 1;
-      return;
-    }
-
-  gdk_pixbuf_loader_set_size (loader,
-                              width * loader_data->scale_factor,
-                              height * loader_data->scale_factor);
-}
-
-static GdkPaintable *
-load_scalable_with_loader (GFile *file,
-                           int    scale_factor)
-{
-  GdkPixbufLoader *loader;
-  GBytes *bytes;
-  GdkPixbufAnimation *animation;
-  GdkPaintable *result, *scaler;
-  LoaderData loader_data;
-
-  result = NULL;
-
-  loader = gdk_pixbuf_loader_new ();
-  loader_data.scale_factor = scale_factor;
-
-  g_signal_connect (loader, "size-prepared", G_CALLBACK (on_loader_size_prepared), &loader_data);
-
-  bytes = g_file_load_bytes (file, NULL, NULL, NULL);
-  if (bytes == NULL)
-    goto out1;
-
-  if (!gdk_pixbuf_loader_write_bytes (loader, bytes, NULL))
-    goto out2;
-
-  if (!gdk_pixbuf_loader_close (loader, NULL))
-    goto out2;
-
-  animation = gdk_pixbuf_loader_get_animation (loader);
-  if (animation == NULL)
-    goto out2;
-
-  result = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (gdk_pixbuf_animation_get_static_image (animation)));
-  scaler = gtk_scaler_new (result, loader_data.scale_factor);
-  g_object_unref (result);
-  result = scaler;
-
-out2:
-  g_bytes_unref (bytes);
-out1:
-  gdk_pixbuf_loader_close (loader, NULL);
-  g_object_unref (loader);
-
-  return result;
-}
-
 /**
  * gtk_picture_set_file: (attributes org.gtk.Method.set_property=file)
  * @self: a `GtkPicture`
@@ -657,7 +586,7 @@ gtk_picture_set_file (GtkPicture *self,
   g_set_object (&self->file, file);
   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
 
-  paintable = load_scalable_with_loader (file, gtk_widget_get_scale_factor (GTK_WIDGET (self)));
+  paintable = gdk_paintable_new_from_file_scaled (file, gtk_widget_get_scale_factor (GTK_WIDGET (self)));
   gtk_picture_set_paintable (self, paintable);
   g_clear_object (&paintable);